package com.ssy.lingxi.platform.manage.serviceimpl.mobile;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.platform.manage.constant.CommonBooleanEnum;
import com.ssy.lingxi.platform.manage.constant.ShelfEnum;
import com.ssy.lingxi.platform.manage.entity.content.*;
import com.ssy.lingxi.platform.manage.model.request.common.CommonIdRequest;
import com.ssy.lingxi.platform.manage.model.request.content.CollectRequest;
import com.ssy.lingxi.platform.manage.model.request.content.InformationListReq;
import com.ssy.lingxi.platform.manage.model.response.InformationDetailResp;
import com.ssy.lingxi.platform.manage.model.response.InformationListResp;
import com.ssy.lingxi.platform.manage.repository.ContentColumnRepository;
import com.ssy.lingxi.platform.manage.repository.ContentInformationCollectRepository;
import com.ssy.lingxi.platform.manage.repository.ContentInformationHistoryRepository;
import com.ssy.lingxi.platform.manage.repository.ContentInformationRepository;
import com.ssy.lingxi.platform.manage.service.mobile.IInformationMobileService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * mobile - 资讯 - 业务实现层
 * @author fhj
 * @version 2.0.0
 * @date 2021/08/31
 */
@Service
public class InformationMobileServiceImpl implements IInformationMobileService {

    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private ContentColumnRepository contentColumnRepository;
    @Resource
    private ContentInformationRepository contentInformationRepository;
    @Resource
    private ContentInformationCollectRepository contentInformationCollectRepository;
    @Resource
    private ContentInformationHistoryRepository contentInformationHistoryRepository;

    @Override
    public Wrapper<PageData<InformationListResp>> list(InformationListReq req) {
        //查询表实体 - 资讯
        QContentInformation contentInformation = QContentInformation.contentInformation;

        //查询条件构造 - 必要条件
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(contentInformation.status.eq(ShelfEnum.ON_SHELF.getCode()));

        //搜索条件
        if (req.getColumnId() != null) {
            predicates.and(contentInformation.columnId.eq(req.getColumnId()));
        }
        if (CollectionUtil.isNotEmpty(req.getRecommendLabel())) {
            predicates.and(contentInformation.recommendLabel.in(req.getRecommendLabel()));
        }
        if(req.getThirdlyCategoryId() != null) {
            predicates.and(contentInformation.thirdlyCategoryId.eq(req.getThirdlyCategoryId()));
        }
        if(StringUtils.isNotEmpty(req.getKeyword())) {
            List<ContentColumn> columnList = contentColumnRepository.findAllByNameContainingAndStatus(req.getKeyword(), CommonBooleanEnum.YES.getCode());
            List<Long> columnIdList = columnList.stream().map(ContentColumn::getId).collect(Collectors.toList());
            predicates.and(
                    contentInformation.title.like("%" + req.getKeyword() + "%")
                            .or(contentInformation.digest.like("%" + req.getKeyword() + "%")
                                    .or(contentInformation.content.like("%" + req.getKeyword() + "%")
                                            .or(contentInformation.firstCategoryName.like("%" + req.getKeyword() + "%")
                                                    .or(contentInformation.secondCategoryName.like("%" + req.getKeyword() + "%")
                                                            .or(contentInformation.thirdlyCategoryName.like("%" + req.getKeyword() + "%")
                                                                    .or(contentInformation.columnId.in(columnIdList)))))))
            );
        }


        //查询
        JPAQuery<InformationListResp> query = jpaQueryFactory.select(
                Projections.bean(
                        InformationListResp.class,
                        contentInformation.id,
                        contentInformation.columnId,
                        contentInformation.title,
                        contentInformation.readCount,
                        contentInformation.collectCount,
                        contentInformation.imageUrl,
                        contentInformation.digest,
                        contentInformation.createTime
                )
        ).from(contentInformation).where(predicates);

        //总记录数
        long totalCount = query.fetchCount();

        //排序（待添加枚举类）
        if (req.getSortType().equals(1)) {
            query.orderBy(contentInformation.createTime.desc());
        }
        if (req.getSortType().equals(2)) {
            query.orderBy(contentInformation.sort.asc());
        }
        if (req.getSortType().equals(3)) {
            query.orderBy(contentInformation.createTime.desc());
        }
        if (req.getSortType().equals(4)) {
            query.orderBy(contentInformation.readCount.desc());
        }
        if (req.getSortType().equals(5)) {
            query.orderBy(contentInformation.collectCount.desc());
        }

        //列表数据
        List<InformationListResp> list = query.offset((req.getCurrent() - 1) * req.getPageSize()).limit(req.getPageSize()).fetch();

        //封装栏目名称
        List<ContentColumn> allColumn = contentColumnRepository.findAll();
        list = list.stream().peek(a -> {
            ContentColumn contentColumn = allColumn.stream().filter(b ->
                    b.getId().equals(a.getColumnId())
            ).findFirst().orElse(new ContentColumn());
            a.setColumnName(contentColumn.getName());
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(totalCount, list));
    }

    @Override
    public Wrapper<InformationDetailResp> detail(CommonIdRequest request, UserLoginCacheDTO user) {
        //根据id获取资讯
        ContentInformation information = contentInformationRepository.findById(request.getId()).orElse(null);
        if (information == null) {
            throw new BusinessException(ResponseCode.MAN_RECORDS_DON_T_EXIST);
        }
        if (information.getStatus().equals(ShelfEnum.OFF_SHELF.getCode())) {
            throw new BusinessException(ResponseCode.MAN_DISABLE);
        }

        //拷贝
        InformationDetailResp resp = new InformationDetailResp();
        BeanUtils.copyProperties(information, resp);

        //栏目名称
        ContentColumn contentColumn = contentColumnRepository.findById(resp.getColumnId()).orElse(new ContentColumn());
        resp.setColumnName(contentColumn.getName());

        //收藏状态
        if (user != null) {
            Boolean collectStatus = contentInformationCollectRepository.existsByInformationIdAndMemberIdAndUserId(information.getId(), user.getMemberId(), user.getUserId());
            resp.setCollectStatus(collectStatus);

            //保存当前登录用户的浏览资讯记录
            ContentInformationHistory  informationHistory = contentInformationHistoryRepository.findByUserIdAndInformationId(user.getUserId(), information.getId());
            if (informationHistory != null) {
                informationHistory.setCreateTime(System.currentTimeMillis());
            }else {
                informationHistory = new ContentInformationHistory();
                informationHistory.setUserId(user.getUserId());
                informationHistory.setInformationId(information.getId());
            }

            contentInformationHistoryRepository.save(informationHistory);
        }

        //查看详情增加浏览量
        information.setReadCount(information.getReadCount() + 1);
        contentInformationRepository.saveAndFlush(information);

        return Wrapper.success(resp);
    }

    @Override
    @Transactional
    public Wrapper<Void> collect(CollectRequest request, UserLoginCacheDTO user) {
        if (request.getStatus()) {
            if (contentInformationCollectRepository.existsByInformationIdAndMemberIdAndUserId(request.getInformationId(), user.getMemberId(), user.getUserId())) {
                return Wrapper.fail("不能重复收藏，请刷新页面");
            }
            ContentInformationCollect collect = new ContentInformationCollect();
            collect.setInformationId(request.getInformationId());
            collect.setMemberId(user.getMemberId());
            collect.setUserId(user.getUserId());
            contentInformationCollectRepository.saveAndFlush(collect);
        } else {
            contentInformationCollectRepository.deleteByInformationIdAndMemberIdAndUserId(request.getInformationId(), user.getMemberId(), user.getUserId());
        }

        //更新资讯收藏数
        contentInformationRepository.findById(request.getInformationId()).ifPresent(information ->
                information.setCollectCount(request.getStatus() ?
                        information.getCollectCount() + 1 : information.getReadCount() - 1)
        );

        return Wrapper.success();
    }

    @Override
    public Wrapper<PageData<InformationListResp>> collectList(PageVO request, UserLoginCacheDTO user) {
        //分页查询当前登录用户收藏资讯信息
        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("createTime").descending());
        Page<ContentInformationCollect> result = contentInformationCollectRepository.findAllByMemberIdAndUserId(user.getMemberId(), user.getUserId(), page);
        List<ContentInformationCollect> collectList = result.getContent();

        if (CollectionUtil.isNotEmpty(collectList)) {
            List<Long> informationIdList = collectList.stream().map(ContentInformationCollect::getInformationId).collect(Collectors.toList());
            List<ContentInformation> informationList = contentInformationRepository.findAllById(informationIdList);
            if (CollectionUtil.isNotEmpty(informationList)) {
                List<ContentColumn> allColumn = contentColumnRepository.findAll();

                List<InformationListResp> responses = informationList.stream().map(a -> {
                    InformationListResp resp = new InformationListResp();
                    BeanUtils.copyProperties(a, resp);

                    ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(null);
                    resp.setColumnName(contentColumn == null ? "" : contentColumn.getName());

                    Long collectTime = collectList.stream().filter(b -> b.getInformationId().equals(a.getId())).mapToLong(ContentInformationCollect::getCreateTime).findFirst().orElse(0L);
                    resp.setCollectTime(collectTime);
                    return resp;
                }).sorted(Comparator.comparing(InformationListResp::getCollectTime).reversed()).collect(Collectors.toList());

                return Wrapper.success(new PageData<>(result.getTotalElements(), responses));
            }
        }

        return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
    }

    @Override
    public Wrapper<List<InformationListResp>> history(UserLoginCacheDTO user) {
        List<ContentInformationHistory> historyList = contentInformationHistoryRepository.findByUserId(user.getUserId(), Sort.by("createTime").descending());

        List<Long> informationIdList = historyList.stream().map(ContentInformationHistory::getInformationId).collect(Collectors.toList());

        List<ContentInformation> informationList = contentInformationRepository.findAllById(informationIdList);

        List<ContentColumn> allColumn = contentColumnRepository.findAll();

        List<InformationListResp> respList = informationList.stream().map(a -> {
            InformationListResp resp = new InformationListResp();
            BeanUtils.copyProperties(a, resp);

            ContentColumn contentColumn = allColumn.stream().filter(b -> b.getId().equals(a.getColumnId())).findFirst().orElse(null);
            resp.setColumnName(contentColumn == null ? "" : contentColumn.getName());

            return resp;
        }).collect(Collectors.toList());

        return Wrapper.success(respList);
    }
}
